package com.logic.modular.game.season.server.service.impl;

import cn.hutool.core.lang.Pair;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.comment.exception.ServiceException;
import com.comment.pojo.domain.bag.BagItem;
import com.comment.pojo.domain.logic.core.CoreConfig;
import com.comment.pojo.domain.logic.core.CoreTaskConfig;
import com.logic.comment.util.XsRedisUtils;
import com.logic.modular.game.player.bag.service.BagItemServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType2ServiceImpl;

import com.logic.modular.game.season.server.domain.PlayerSeason;
import com.logic.modular.game.season.server.service.PlayerSeasonService;
import com.logic.modular.gameCore.config.mapper.CoreConfigMapper;
import com.logic.modular.gameCore.config.service.impl.CoreConfigServiceImpl;
import com.logic.modular.gameCore.cultivate.task.service.CoreTaskConfigServiceImpl;
import com.logic.modular.gameCore.season.info.domain.CoreSeasonAward;
import com.logic.modular.gameCore.season.info.mapper.CoreSeasonAwardMapper;
import com.logic.modular.gameCore.season.info.service.impl.CoreSeasonAwardServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class PlayerSeasonServiceImpl implements PlayerSeasonService {
    private static final String KEY_PLAYER_SEASON = "player:%d:season";
    private static final Long war_command_experience = 6L;
    @Resource
    private XsRedisUtils xsRedisUtils;
    @Resource
    private CoreSeasonAwardMapper coreSeasonAwardMapper;
    @Resource
    private BagItemServiceImpl bagItemServiceImpl;
    @Resource
    private CoreTaskConfigServiceImpl coreTaskConfigServiceImpl;
    @Resource
    private CoreSeasonAwardServiceImpl coreSeasonAwardServiceImpl;
    @Resource
    private CoreConfigServiceImpl coreConfigServiceImpl;
    @Resource
    private PlayerPropType2ServiceImpl playerPropType2Service;

    public void save(PlayerSeason entity) {
        xsRedisUtils.set(String.format(KEY_PLAYER_SEASON, entity.getUid()), entity, 60, TimeUnit.MINUTES);
    }

    private PlayerSeason getById(Long playerId) {
        return xsRedisUtils.getToBean(String.format(KEY_PLAYER_SEASON, playerId), PlayerSeason.class);
    }

    @Override
    public PlayerSeason obtain(Long playerId) {
        PlayerSeason playerSeason = getById(playerId);
        if (playerSeason == null) {
            playerSeason = new PlayerSeason();
            playerSeason.setUid(playerId);
            save(playerSeason);
        }
        return playerSeason;
    }

    @Override
    public void claimLevelRewards(Long playerId, Integer leve, Integer lv, Long bagItemId) {
        PlayerSeason playerSeason = obtain(playerId);

        CoreSeasonAward targetLeve = coreSeasonAwardMapper.selectOne(
                new LambdaQueryWrapper<CoreSeasonAward>()
                        .eq(CoreSeasonAward::getLevel, leve)
        );


        BagItem one = bagItemServiceImpl.getOne(new LambdaQueryWrapper<BagItem>().eq(BagItem::getUid, playerId)
                .eq(BagItem::getCorePropId, war_command_experience));
        BigDecimal haveExp = one == null ? BigDecimal.ZERO : one.getNum();

        if (haveExp.intValue() < targetLeve.getTotalExp()) {
            throw new ServiceException("战令等级不足");
        }


        if (lv == 1) {
            if (playerSeason.getReceivedRewards1Ids().contains(targetLeve.getId())) {
                throw new ServiceException("已领取");
            }
            Map<Long, Integer> generalAward = targetLeve.getGeneralAward();
            generalAward.forEach((id, num) -> bagItemServiceImpl.obtainBagItem(playerId, id, new BigDecimal(num)));
            playerSeason.receivedRewards1Ids.add(targetLeve.getId());
            save(playerSeason);
        }
        if (lv == 2) {
            if (playerSeason.getReceivedRewards2Ids().contains(targetLeve.getId())) {
                throw new ServiceException("已领取");
            }
            // 判定付费状态
            if (playerPropType2Service.noneMatchSeason(playerId, bagItemId)) {
                throw new ServiceException("未购买战令卡");
            }

            Map<Long, Integer> advancedAward = targetLeve.getAdvancedAward();
            advancedAward.forEach((id, num) -> bagItemServiceImpl.obtainBagItem(playerId, id, new BigDecimal(num)));
            playerSeason.receivedRewards2Ids.add(targetLeve.getId());
            save(playerSeason);
        }
    }

    @Override
    public boolean purchaseLevel(Long playerId, Integer targetLevel) {
        BagItem one = bagItemServiceImpl.getOne(new LambdaQueryWrapper<BagItem>().eq(BagItem::getUid, playerId)
                .eq(BagItem::getCorePropId, war_command_experience));
        BigDecimal haveExp = one == null ? BigDecimal.ZERO : one.getNum();
        long exp = haveExp.intValue();
        if (exp == 0) {
            CoreConfig byId = coreConfigServiceImpl.getById(12);
            BigDecimal value1 = byId.getValue1();
            exp = value1.intValue();
            bagItemServiceImpl.obtainBagItem(playerId, war_command_experience, BigDecimal.valueOf(exp));
        }

        Integer currentLevel = coreSeasonAwardServiceImpl.getLevel(exp);

        if (currentLevel >= targetLevel) {
            throw new ServiceException("当前等级超过目标等级" + currentLevel + "," + targetLevel);
        }

        List<CoreSeasonAward> coreSeasonAwards = coreSeasonAwardMapper.selectList(
                new LambdaQueryWrapper<CoreSeasonAward>()
                        .between(CoreSeasonAward::getLevel, currentLevel, targetLevel)
        );

        long obtainExp = 0;

        CoreSeasonAward max = coreSeasonAwards.stream().max(Comparator.comparing(CoreSeasonAward::getLevel)).get();
        CoreSeasonAward min = coreSeasonAwards.stream().min(Comparator.comparing(CoreSeasonAward::getLevel)).get();
        List<Map<Long, Integer>> costList = coreSeasonAwards.stream().map(CoreSeasonAward::getCost).collect(Collectors.toList());

        obtainExp = exp - min.getTotalExp();
        obtainExp = obtainExp + max.getTotalExp() - min.getTotalExp();
        for (Map<Long, Integer> map : costList) {
            map.forEach((id, num) -> bagItemServiceImpl.obtainBagItem(playerId, id, new BigDecimal(num).negate()));
        }
        bagItemServiceImpl.obtainBagItem(playerId, war_command_experience, BigDecimal.valueOf(obtainExp));
        return true;
    }

    public List<CoreTaskConfig> viewBattleOrderTasks() {
        return coreTaskConfigServiceImpl.list(
                new LambdaQueryWrapper<CoreTaskConfig>().
                        eq(CoreTaskConfig::getGrouping, 2)
        );
    }

    public Pair<Long, Long> obtainTheStartAndEndTimesOfTheSeason() {
        return playerPropType2Service.obtainSeasonDay();
    }
}